classdef dotsPlayablePPAOneTone < dotsPlayablePPA
    % @class dotsPlayablePPAOneTone
    %
    % PPA for "PsychPortAudio"
    %   type 'help PsychPortAudio' for details
    % Play sounds using high-precision sound driver
    %   implemented in Psychtoolbox 3
    
    properties (SetObservable = true)
        
        % duh, in cycles/s
        toneFrequency;
        
        % double duh, in s
        toneDuration;
        
        % on/off ramp duration, in ms
        rampDuration=10;
        
        % 'left', 'right', or 'both'
        channel = 'both';
    end
    
    properties (SetObservable = false)
        
        % returned by PsychPortAudio('FillBuffer');
        underflow;

        % returned by PsychPortAudio('FillBuffer');
        nextSampleStartIndex;

        % returned by PsychPortAudio('FillBuffer');
        nextSampleETASecs;

    end
    
    methods
        
        function self = dotsPlayablePPAOneTone
            self = self@dotsPlayablePPA;
            
            % check channels
            if self.channels < 2 && self.channel == 'both'
                self.channel = 'left';
            end
        end
        
        function prepareToPlay(self)
            
            % compute sinusoid
            nCycles       = self.toneFrequency   * self.toneDuration;
            nSamples      = self.sampleFrequency * self.toneDuration;
            vals          = sin(linspace(0, nCycles*2*pi, nSamples));
            
            % add on/off ramps
            nRampSamples  = min(nSamples/2, self.sampleFrequency * self.rampDuration/1000);
            ramp          = linspace(0,1,nRampSamples);
            vals(1:nRampSamples)         = vals(1:nRampSamples).*ramp;
            vals(end-nRampSamples+1:end) = vals(end-nRampSamples+1:end).*ramp;
            
            if strcmp(self.channel, 'left')
                self.waveform = [vals; zeros(size(vals))];
            elseif strcmp(self.channel, 'right')
                self.waveform = [zeros(size(vals)); vals];
            else
                self.waveform = [vals; vals];
            end
            
            [self.underflow,self.nextSampleStartIndex,self.nextSampleETASecs] = ...
                PsychPortAudio('FillBuffer', self.pahandle, ...
                self.waveform);
        end
    end
end